﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace Excel_2010_Measure_Reader
{
    public partial class ExcelTreeView : TreeView
    {
        public ExcelTreeView()
        {
            InitializeComponent();
        }

        public void ReadDrives()
        {
            var driveNodes = Environment.GetLogicalDrives()
                .OrderBy(drive => drive)
                .Select(drive => (new TreeNode {Text = drive, Tag = drive}));

            foreach (var driveNode in driveNodes)
            {
                driveNode.ImageIndex = 0;
                driveNode.SelectedImageIndex = 0;

                driveNode.Nodes.Add(new TreeNode {Text = @".", Tag = @"."});
                Nodes.Add(driveNode);
                driveNode.HideCheckBox();
            }

            // Hookup handler after reading drives
            BeforeExpand += ExcelFileTreeView_BeforeExpand;
        }

        private NodeTypeEnum GetNodeType(TreeNode node)
        {
            return (NodeTypeEnum) GetImageIndex(node);
        }

        private void ExcelFileTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.HasChildren() && (e.Node.Nodes[0].Text == @"."))
            {
                e.Node.Nodes.Clear();

                try
                {
                    IEnumerable<TreeNode> subDirectories = Directory.EnumerateDirectories(e.Node.Tag.ToString())
                        .OrderBy(directory => directory)
                        .Select(directory => new TreeNode {Text = Path.GetFileName(directory ?? ""), Tag = directory});

                    foreach (TreeNode subDirectory in subDirectories)
                    {
                        subDirectory.ImageIndex = 1;
                        subDirectory.SelectedImageIndex = 1;
                        subDirectory.Nodes.Add(new TreeNode {Text = @".", Tag = @"."});
                        e.Node.Nodes.Add(subDirectory);
                        subDirectory.HideCheckBox();
                    }

                    IEnumerable<TreeNode> files = Directory.EnumerateFiles(e.Node.Tag.ToString(), "*.xls?")
                        .OrderBy(file => file.ToUpper())
                        .Select(file => new TreeNode {Text = Path.GetFileName(file ?? ""), Tag = file});

                    foreach (TreeNode file in files)
                    {
                        file.ImageIndex = 2;
                        file.SelectedImageIndex = 2;
                        e.Node.Nodes.Add(file);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    // Do not want to drill into unauthoried directories
                }
            }
        }


        private int GetImageIndex(TreeNode node)
        {
            return node.IsSelected ? node.SelectedImageIndex : node.ImageIndex;
        }

        private List<string> ReadNodes(TreeNodeCollection nodes, List<string> fileNames)
        {
            //IOrderedEnumerable<TreeNode> 
            var treeNodes = nodes.OfType<TreeNode>().OrderBy(node => node.Tag.ToString());

            foreach (var node in treeNodes)
            {
                if (node.Nodes.Count > 0)
                {
                    ReadNodes(node.Nodes, fileNames);
                }
                else if (node.Checked)
                {
                    fileNames.Add(node.Tag.ToString());
                }
            }
            return fileNames;
        }


        public List<string> GetFilePaths()
        {
            return ReadNodes(Nodes, new List<string>());
        }

        private void CheckFiles(TreeNode directoryNode, CheckOptionEnum checkOption)
        {
            var checkState = true;
            var recur = true;

            if (checkOption == CheckOptionEnum.CheckAll)
            {
                directoryNode.Expand();
                recur = false;
            }
            else if (checkOption == CheckOptionEnum.CheckAllRecursive)
            {
                directoryNode.Expand();
            }
            else if (checkOption == CheckOptionEnum.UncheckAll)
            {
                checkState = false;
                recur = false;
            } 
            else if (checkOption == CheckOptionEnum.UncheckAllRecursive)
            {
                checkState = false;
                directoryNode.Collapse();
            }

            foreach (TreeNode node in directoryNode.Nodes)
            {
                if (IsDirectoryNode(node) && recur)
                {
                    CheckFiles(node, checkOption);
                }
                else if (IsFileNode(node))
                {
                    node.Checked = checkState;
                }
            }
        }

        private bool IsDirectoryNode(TreeNode node)
        {
            return 1 == (node.IsSelected ? node.SelectedImageIndex : node.ImageIndex);
        }

        private bool IsFileNode(TreeNode node)
        {
            return 2 == (node.IsSelected ? node.SelectedImageIndex : node.ImageIndex);
        }

        private void ExcelTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (NodeTypeEnum.Directory == GetNodeType(e.Node))
            {
                var checkOptionsDialog = new CheckOptionsDialog();
                checkOptionsDialog.ShowDialog();
                var checkOption = checkOptionsDialog.CheckOption;

                if (checkOption != CheckOptionEnum.Cancel)
                {
                    CheckFiles(e.Node, checkOption);
                }
            }
        }
    }
}